/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.registration.business.weather;

import it.polimi.registration.business.security.boundary.CalendarManager;
import it.polimi.registration.business.security.boundary.NotificationManager;
import it.polimi.registration.business.security.boundary.UserManager;
import it.polimi.registration.business.security.entity.BadWeather;
import it.polimi.registration.business.security.entity.Event;
import it.polimi.registration.business.security.entity.Forecast;
import it.polimi.registration.business.security.entity.User;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.ScheduleExpression;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;

/**
 *
 * @author miglie
 */
@Startup
@Singleton
public class WeatherChecker {

	private static final Logger logger = Logger.getLogger(WeatherChecker.class
			.getName());

	//private Client client;

	@PersistenceContext
	EntityManager em;
    
    @EJB
    private NotificationManager nm;
    
    @EJB
    private CalendarManager cm;
    
    @EJB
    private UserManager um;

	@Resource
	private TimerService timerService;

	/*@PostConstruct
	private void init() {
		logger.log(Level.INFO, "WeatherChecker created");
		client = ClientBuilder.newClient();

		ScheduleExpression every3Hours = new ScheduleExpression().hour("*");
		timerService.createCalendarTimer(every3Hours,
				new TimerConfig("", false));
	}*/

	@Schedule(second = "*", minute = "*", hour = "*/1", persistent = false)
	public void checkWeatherAutoTimer() {
		/*logger.log(Level.INFO,
				"{0}: automatic timer expired, checking the weather",
				new Date());*/
		updateForecasts();

	}

	@Timeout
	public void checkWeatherProgTimer() {
		logger.log(Level.INFO,
				"{0}: programmatic timer expired, checking the weather",
				new Date());
	}

	@SuppressWarnings("unchecked")
	private void updateForecasts() {
		List<Event> le = em.createQuery("SELECT t FROM Event t").getResultList();

		for (Event e : le) {
			Calendar c = new GregorianCalendar();
			Forecast f = null;
			long timespan = (e.getDate().getTime().getTime() - c.getTime().getTime()) / 1000;
			if (timespan >= 0 && timespan < WeatherConstants.SIXTEEN_DAYS) {
				f = new Forecast(e, e.getDate(), e.getLocation());
				e.setForecast(f);

				try {
					f.update();
				} catch (Exception ex) {
					StringWriter errors = new StringWriter();
					ex.printStackTrace(new PrintWriter(errors));
					logger.log(Level.SEVERE, errors.toString());
				}
			}
			
			if(timespan < WeatherConstants.THREE_DAYS) {
				BadWeather bw;
				Calendar proposition = getProposition(e);
				for(User u : e.getInvitedUsers()) {
					bw = new BadWeather(e, u, proposition);
		        	nm.save(bw);
		        	um.merge(u);
		        	cm.merge(u.getCalendar());
				}
				
				bw = new BadWeather(e, e.getOwner(), proposition);
	        	nm.save(bw);
	        	um.merge(e.getOwner());
	        	cm.merge(e.getOwner().getCalendar());
			}
		}
	}

	private Calendar getProposition(Event e) {
		Calendar cal=GregorianCalendar.getInstance();
		long ts;
		try {
			ts = (new PropositionFactory(e)).getNextSunnyDay();			
			if(ts == 0)
				cal = e.getDate();
			else
				cal.setTime(new Timestamp(ts));
		} catch (Exception e1) {
			cal = e.getDate();
		}
		return cal;
	}

}
